"""
节点管理路由
"""
import json
from typing import Optional, List
from fastapi import APIRouter, Depends, HTTPException, Form
from fastapi.responses import JSONResponse
from sqlalchemy.orm import Session
from database import get_db
from schemas import (
    NodeInfo, NodeCreate, NodeUpdate, GenericResponse, ListResponse, DataResponse, EdgeSampleCollectionRequest, SampleCollectionRequest,
    NodeMonitoringInfo, NodeCPUInfo, NodeMemoryInfo, NodeGPUInfo, NodeNetworkInfo, NodeStorageInfo
)
from services import NodeService, DatasetService
from exceptions import NotFoundException, ValidationException
from response_utils import success_response, list_response
from utils import LogManager

router = APIRouter(prefix="/api/v1", tags=["节点管理"])

# 节点服务实例
node_service = NodeService()
dataset_service = DatasetService()
logger = LogManager.get_logger(__name__)

@router.get("/nodes", response_model=ListResponse[NodeInfo])
async def list_nodes(
    node_type: Optional[str] = None,  # 'cloud' 或 'edge'
    status: Optional[str] = None,
    location: Optional[str] = None,
    page: int = 1,
    page_size: int = 20,
    db: Session = Depends(get_db)
):
    """获取节点列表"""
    nodes, total_count = node_service.list_nodes(
        db, page, page_size, node_type, status, location
    )
    
    # 调用服务层的统计方法
    summary = node_service.get_nodes_summary(db, node_type, status, location)
    
    return list_response(
        items=nodes,
        total_count=total_count,
        summary=summary,
        message="查询成功"
    )

@router.post("/nodes", response_model=DataResponse[NodeInfo])
async def create_node(
    node: NodeCreate,
    db: Session = Depends(get_db)
):
    """创建或更新节点（边侧注册时自动适配）"""
    try:
        created_node, is_new = node_service.create_or_update_node(db, node)
        
        if is_new:
            message = "节点创建成功"
        else:
            message = "节点更新成功"
            
        return success_response(data=created_node, message=message)
    except ValidationException as e:
        raise HTTPException(status_code=400, detail=e.message)

@router.get("/nodes/{node_id}", response_model=DataResponse[NodeInfo])
async def get_node(node_id: str, db: Session = Depends(get_db)):
    """获取节点详情"""
    try:
        node = node_service.get_node_by_id(db, node_id)
        return success_response(data=node, message="查询成功")
    except NotFoundException as e:
        raise HTTPException(status_code=404, detail=e.message)

@router.put("/nodes/{node_id}", response_model=DataResponse[NodeInfo])
async def update_node(
    node_id: str,
    node_update: NodeUpdate,
    db: Session = Depends(get_db)
):
    """更新节点信息"""
    try:
        updated_node = node_service.update_node(db, node_id, node_update)
        return success_response(data=updated_node, message="节点更新成功")
    except NotFoundException as e:
        raise HTTPException(status_code=404, detail=e.message)

@router.post("/nodes/reload", response_model=DataResponse[dict])
async def reload_nodes(db: Session = Depends(get_db)):
    """重新加载节点配置"""
    result = node_service.reload_nodes(db)
    return success_response(data=result, message="节点配置重新加载成功")

@router.get("/edge-data/{node_id}/samples/info", response_model=DataResponse[dict])
async def get_edge_samples_info(node_id: str, db: Session = Depends(get_db)):
    """获取边侧样本信息"""
    try:
        samples_info = await node_service.get_edge_samples_info(db, node_id)
        return success_response(data=samples_info, message="查询成功")
    except NotFoundException as e:
        raise HTTPException(status_code=404, detail=e.message)
    except ValidationException as e:
        raise HTTPException(status_code=502, detail=e.message) # 502 Bad Gateway, as we failed to talk to a downstream service

@router.post("/edge-data/{node_id}/samples/aggregate", response_model=DataResponse[dict])
async def aggregate_edge_samples(
    node_id: str,
    aggregation_type: str = Form("recent"),
    limit: int = Form(100),
    db: Session = Depends(get_db)
):
    """请求边侧数据聚合"""
    try:
        result = await node_service.aggregate_edge_samples(
            db, node_id, aggregation_type, limit
        )
        return success_response(data=result, message="数据聚合请求成功")
    except NotFoundException as e:
        raise HTTPException(status_code=404, detail=e.message)
    except ValidationException as e:
        raise HTTPException(status_code=502, detail=e.message)

@router.post("/edge-data/{node_id}/model/deploy", response_model=DataResponse[dict])
async def deploy_model_to_edge(
    node_id: str,
    model_id: str = Form(...),
    deployment_config: Optional[str] = Form(None), # JSON string
    db: Session = Depends(get_db)
):
    """部署模型到边侧"""
    try:
        config_dict = json.loads(deployment_config) if deployment_config else {}
        result = await node_service.deploy_model_to_edge(
            db, node_id, model_id, config_dict
        )
        return success_response(data=result, message="模型部署成功")
    except (NotFoundException, ValidationException) as e:
        raise HTTPException(status_code=400, detail=e.message)
    except json.JSONDecodeError:
        raise HTTPException(status_code=400, detail="Invalid JSON format for deployment_config")

@router.get("/edge-nodes/samples", response_model=ListResponse[dict])
async def get_all_edge_nodes_samples_info(
    page: int = 1,
    page_size: int = 20,
    status: Optional[str] = None,  # 节点状态过滤: online, offline
    location: Optional[str] = None,  # 位置过滤
    db: Session = Depends(get_db)
):
    """获取所有边侧节点的样本情况（支持分页）"""
    try:
        result = await node_service.get_all_edge_nodes_with_samples_info_paginated(
            db, page=page, page_size=page_size, status=status, location=location
        )
        logger.info(f"result: {result}")
        
        # 创建分页信息
        from response_utils import create_pagination_info
        pagination = create_pagination_info(page, page_size, result["total_count"])
        
        return list_response(
            items=result["nodes"],
            total_count=result["total_count"],
            pagination=pagination,
            summary=result.get("summary"),
            message="获取边侧节点样本信息成功"
        )
    except ValidationException as e:
        raise HTTPException(status_code=502, detail=e.message)
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取边侧节点样本信息失败: {str(e)}")

@router.post("/edge-nodes/status/update", response_model=DataResponse[dict])
async def update_edge_nodes_status(
    node_ids: Optional[List[str]] = None,
    db: Session = Depends(get_db)
):
    """批量更新边侧节点状态"""
    try:
        result = await node_service.batch_update_edge_nodes_status(db, node_ids)
        return success_response(data=result, message="边侧节点状态更新成功")
    except ValidationException as e:
        raise HTTPException(status_code=400, detail=e.message)
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"更新边侧节点状态失败: {str(e)}")

@router.post("/edge-nodes/{node_id}/samples/collect", response_model=DataResponse[dict])
async def collect_samples_from_edge_node(
    node_id: str,
    request: SampleCollectionRequest,
    db: Session = Depends(get_db)
):
    """从边侧节点归集样本并创建数据集（新策略：下载压缩包）"""
    try:
        # 构建聚合参数
        aggregation_params = {
            "difficulty_threshold": request.difficulty_threshold,
            "time_start": request.time_start,
            "time_end": request.time_end,
            "max_samples": request.max_samples,
            "scenario": request.scenario
        }
        
        # 1. 调用边侧样本聚合接口，让边侧打包样本
        collection_result = await node_service.aggregate_edge_samples(
            db, node_id, "custom", request.max_samples, aggregation_params
        )
        
        if not collection_result or not collection_result.get("success"):
            error_msg = collection_result.get("message", "未知错误") if collection_result else "调用边侧接口失败"
            return success_response(
                data={"collection_result": collection_result},
                message=f"边侧样本聚合失败: {error_msg}"
            )
        
        # 2. 下载并处理边侧压缩包
        try:
            download_result = await node_service.download_and_process_edge_samples(
                db, node_id, request.scenario, aggregation_params, request.base_dataset_id
            )
            
            if download_result.get("success"):
                return success_response(
                    data={
                        "collection_result": collection_result,
                        "download_result": download_result,
                        "dataset": download_result.get("dataset")
                    },
                    message="样本归集和数据集创建成功"
                )
            else:
                return success_response(
                    data={
                        "collection_result": collection_result,
                        "download_error": download_result.get("error")
                    },
                    message="边侧样本聚合成功，但压缩包下载失败"
                )
                
        except Exception as download_error:
            logger.error(f"下载边侧压缩包失败: {str(download_error)}")
            return success_response(
                data={
                    "collection_result": collection_result,
                    "download_error": str(download_error)
                },
                message="边侧样本聚合成功，但压缩包下载失败"
            )
        
    except NotFoundException as e:
        raise HTTPException(status_code=404, detail=e.message)
    except ValidationException as e:
        raise HTTPException(status_code=400, detail=e.message)
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"样本归集失败: {str(e)}")

@router.get("/scenarios/{scenario}/base-datasets", response_model=DataResponse[List[dict]])
async def get_base_datasets_by_scenario(
    scenario: str,
    db: Session = Depends(get_db)
):
    """根据场景获取基础数据集列表"""
    try:
        datasets = dataset_service.get_base_datasets_by_scenario(db, scenario)
        
        result = []
        for dataset in datasets:
            result.append({
                "dataset_id": dataset.dataset_id,
                "name": dataset.name,
                "description": dataset.description,
                "sample_count": dataset.sample_count,
                "data_size": dataset.data_size,
                "created_at": dataset.created_at.isoformat() if dataset.created_at else None
            })
        
        return success_response(
            data=result, 
            message=f"获取场景 {scenario} 的基础数据集成功"
        )
        
    except ValidationException as e:
        raise HTTPException(status_code=400, detail=e.message)
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取基础数据集失败: {str(e)}")

@router.get("/nodes-monitoring", response_model=ListResponse[NodeMonitoringInfo])
async def get_nodes_monitoring(
    node_type: Optional[str] = None,  # 'cloud' 或 'edge'
    status: Optional[str] = None,
    location: Optional[str] = None,
    page: int = 1,
    page_size: int = 20,
    db: Session = Depends(get_db)
):
    """获取节点监控信息列表（包含详细的CPU、内存、GPU、网络、存储等监控数据）"""
    try:
        # 首先获取普通的节点列表
        nodes, total_count = node_service.list_nodes(
            db, page, page_size, node_type, status, location
        )
        
        # 为每个节点生成监控数据
        monitoring_nodes = []
        for node in nodes:
            monitoring_node = node_service.generate_mock_monitoring_data(node)
            monitoring_nodes.append(monitoring_node)
        
        # 调用服务层的统计方法
        summary = node_service.get_nodes_summary(db, node_type, status, location)
        next_edge_id = "edge-" + str(summary.get("by_type").get("edge")+1)
        next_cloud_id = "cloud-" + str(summary.get("by_type").get("cloud")+1)
        # 把这两个id添加到summary中
        summary["next_edge_id"] = next_edge_id
        summary["next_cloud_id"] = next_cloud_id
        return list_response(
            items=monitoring_nodes,
            total_count=total_count,
            summary=summary,
            message="获取节点监控信息成功"
        )
        
    except Exception as e:
        logger.error(f"获取节点监控信息失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"获取节点监控信息失败: {str(e)}") 